2. Análise Exploratória de Dados (AED)

A Análise Exploratória de Dados (AED) é uma etapa fundamental na ciência de dados, utilizada para entender a estrutura dos dados, identificar padrões, detectar anomalias e gerar insights iniciais antes da modelagem. Neste capítulo, exploraremos os diferentes tipos de dados e como visualizá-los de forma eficiente. Veremos diversos tipos de gráficos, como histogramas, boxplots, scatter plots e heatmaps, utilizando bibliotecas como Pandas, Matplotlib e Seaborn e a principal usada nesse material, o Plotly. A visualização e análise exploratória por si só, nos torna capazes de extrair informações de grande importância para orientar a tomada de decisões e auxilia fortemente na construção de modelos preditivos.

Devemos primeiramente iterar com os diversos tipos de dados presentes nos conjuntos de dados para compreender sua estrutura e como cada variável pode impactar a análise. Identificar se os dados são numéricos, categóricos ou binários é essencial para escolher os métodos estatísticos e gráficos mais adequados.

Abaixo será carregado um dataset para estudo. Tudo em python.

2.1. Biblioteca

Importação dos pacotes usados

import pandas as pd 
import numpy as np
import random
import numpy as np    
import plotly.express as px 
import plotly.io as pio  
import plotly.graph_objs as go 

2.2. Pacotes Essenciais: Pandas e Numpy

Antes de começarmos a análise de dados e visualizações, é importante entender as bibliotecas que usaremos ao longo deste trabalho. Entre as mais importantes estão o Pandas e o Numpy, que serão fundamentais para o processamento e análise de dados. Vamos ver brevemente o que cada uma delas faz:

2.2.1. Pandas

O Pandas é uma biblioteca poderosa para manipulação e análise de dados. Ela oferece estruturas de dados como o DataFrame, que facilita a leitura, a transformação e o resumo de grandes conjuntos de dados de forma eficiente. O Pandas permite importar dados de diversos formatos (CSV, Excel, SQL, etc.), realizar operações como filtragem, agrupamento, e transformações, e também facilita a análise exploratória de dados (AED).

Exemplo de uso:

  • Leitura de arquivos CSV

  • Manipulação de dados em tabelas

  • Análise de dados e criação de resumos estatísticos

2.2.2. Numpy

O Numpy é uma biblioteca fundamental para computação científica em Python. Ela fornece suporte para arrays multidimensionais, que são usados para representar e operar com grandes conjuntos de dados numéricos de maneira rápida e eficiente. Além disso, o Numpy contém funções matemáticas avançadas e operações vetorizadas que ajudam a otimizar o desempenho em cálculos matemáticos.

Exemplo de uso:

  • Criação de arrays e matrizes numéricas

  • Operações matemáticas rápidas em grandes volumes de dados

  • Manipulação de dados para modelagem estatística e aprendizado de máquina

2.2.3. Importância dos Pacotes

Durante este Jupyter-Book, o Pandas será utilizado para carregar, limpar e manipular os dados. Já o Numpy será a base para cálculos matemáticos e operações de alto desempenho. Ambas as bibliotecas são essenciais, pois fornecem a estrutura e a velocidade necessárias para realizar análise exploratória de dados (AED), visualizações gráficas e até modelagem preditiva.

Esses pacotes são fundamentais para trabalharmos de forma eficiente e eficaz com os dados ao longo de todo o conteúdo. Vamos ver como podemos usar essas ferramentas nos próximos capítulos para explorar, visualizar e entender melhor os dados.

2.3. Base de dados

dataset = pd.read_csv('data/census.csv')
dataset.head()
age workclass final-weight education education-num marital-status occupation relationship race sex capital-gain capital-loos hour-per-week native-country income
0 39 State-gov 77516 Bachelors 13 Never-married Adm-clerical Not-in-family White Male 2174 0 40 United-States <=50K
1 50 Self-emp-not-inc 83311 Bachelors 13 Married-civ-spouse Exec-managerial Husband White Male 0 0 13 United-States <=50K
2 38 Private 215646 HS-grad 9 Divorced Handlers-cleaners Not-in-family White Male 0 0 40 United-States <=50K
3 53 Private 234721 11th 7 Married-civ-spouse Handlers-cleaners Husband Black Male 0 0 40 United-States <=50K
4 28 Private 338409 Bachelors 13 Married-civ-spouse Prof-specialty Wife Black Female 0 0 40 Cuba <=50K

Podemos observar diferentes tipos de dados:

  1. Variáveis Numéricas São aquelas que representam valores quantitativos, permitindo operações matemáticas diretas, como média e desvio padrão. No dataset, temos as seguintes variáveis numéricas:

    • age: Idade do indivíduo.

    • final-weight: Peso final atribuído a cada indivíduo no censo.

    • education-num: Número de anos de educação formal.

    • capital-gain: Ganhos de capital.

    • capital-loos: Perdas de capital.

    • hour-per-week: Número de horas trabalhadas por semana.

  2. Variáveis Categóricas São variáveis que representam grupos ou categorias, sem uma ordem numérica natural. No dataset, temos:

workclass: Tipo de emprego (ex: “State-gov”, “Self-emp-not-inc”). education: Nível educacional (ex: “Bachelors”, “Masters”). marital-status: Estado civil (ex: “Never-married”, “Married-civ-spouse”). occupation: Tipo de ocupação (ex: “Adm-clerical”, “Exec-managerial”). relationship: Papel familiar (ex: “Husband”, “Not-in-family”). race: Raça do indivíduo (ex: “White”, “Black”). sex: Gênero (“Male” ou “Female”). native-country: País de origem (ex: “United-States”, “Mexico”).

  1. Variável Binária Variáveis binárias assumem apenas dois valores distintos. No dataset, a variável income se enquadra nessa categoria:

income: Indica se o indivíduo ganha mais ou menos de 50K por ano (<=50K ou >50K).

Para verificar os tipos de dados no Pandas, utilizamos:

print(dataset.dtypes)
age                int64
workclass         object
final-weight       int64
education         object
education-num      int64
marital-status    object
occupation        object
relationship      object
race              object
sex               object
capital-gain       int64
capital-loos       int64
hour-per-week      int64
native-country    object
income            object
dtype: object

Podemos verificar a distribuição da variável binária com:

print(dataset['income'].value_counts())
 <=50K    24720
 >50K      7841
Name: income, dtype: int64

2.4. Visualização Gráfica

A Análise Exploratória de Dados (AED) é uma abordagem fundamental para entender conjuntos de dados, permitindo identificar padrões, outliers e tendências. Além de métodos estatísticos, a visualização gráfica é uma ferramenta essencial para resumir e interpretar as características principais dos dados de forma intuitiva.

Neste capítulo, exploraremos diferentes técnicas de visualização para variáveis numéricas e categóricas, utilizando gráficos que facilitam a interpretação dos dados. O objetivo é fornecer uma visão clara sobre a distribuição, correlação e comportamento das variáveis do nosso dataset.

2.4.1. Uso do Plotly para Visualizações Interativas

Para a construção dos gráficos, optamos pelo uso do Plotly, pois suas visualizações interativas oferecem uma experiência mais rica ao explorar os dados. Quando este livro for visualizado online, o leitor poderá interagir com os gráficos, analisando detalhes específicos ao passar o cursor sobre os elementos ou ampliando regiões de interesse.

Abaixo, um exemplo simples de um histograma interativo para visualizar a distribuição da idade dos indivíduos no dataset:

from plotly.offline import plot
from IPython.display import display, HTML
pio.renderers.default = 'jupyterlab'
def plotly_plot(fig):
    plot(fig, filename='temp-plot.html', auto_open=False)
    display(HTML('temp-plot.html'))
fig = px.histogram(dataset, x="age", nbins=30, title="Distribuição de Idade")
# Gerar e exibir o gráfico de forma interativa
fig.show()
plotly_plot(fig)

Nota: Defini uma função chamada plotly_plot que recebe um objeto de figura e gera um gráfico interativo. O gráfico é salvo em um arquivo HTML temporário e exibido no notebook. Isso se deve pelo fato de que renderizar figuras no jupyterbook ainda é um desafio. Assim, todas as figuras plotly geradas serão mostradas localmente com fig.show e serão plotadas para o Jupyterbook com plotly_plot

2.4.2. Criando um tema personalizado para o plotly

Existem temas pré-definidos para o plotly porém aqui optamos por customizar um tema a fim de deixar os gráficos mais agradáveis visualmente.

custom_template = pio.templates["simple_white"]
 
custom_template.layout.title = {   'y': 0.95 ,
    'font': {'color': 'black', 'family': 'HelveticaNeue-CondensedBold, Helvetica, Sans-serif', 'size': 25}
}
 
custom_template.layout.font =  ({'family': 'Helvetica Neue, Helvetica, Sans-serif', 'size': 17, 'color': '#000000'})
 
custom_template.layout.hovermode = 'x unified'
 
custom_template.data['bar'] =  ( ({
    'textfont': {'color': '#FFFFFF', 'family': 'Helvetica Neue, Helvetica, Sans-serif', 'size': 20},
    'textposition': 'outside',
    'texttemplate': '%{value:.2s}'
}),)
 
custom_template.layout['xaxis']['showgrid'] = True
custom_template.layout['yaxis']['showgrid'] = True
 
custom_template.layout.autosize = False
 
custom_template.layout.width = 900
custom_template.layout.height = 540
 
custom_template.data.scatter = [go.Scatter(marker=dict(symbol="circle", size=7))]
custom_template.layout.colorway = ['#0000FF', '#FF0000'] + list(px.colors.qualitative.G10)[2:]
custom_template.layout.legend = {"itemsizing": "constant", "itemwidth": 30}
 
pio.templates.default = custom_template

Agora com o novo template:

fig = px.histogram(dataset, x="age", nbins=30, title="Distribuição de Idade", template=custom_template)
fig.update_layout(xaxis_title="Idade", yaxis_title="Contagem") # colocando labels em português
fig.show()
plotly_plot(fig)

Podemos discriminar por sexo:

fig = px.histogram(dataset, x="age", color='sex',nbins=30, title="Distribuição de Idade", template=custom_template)
fig.update_layout(xaxis_title="Idade", yaxis_title="Contagem", legend_title_text='sexo') # colocando labels em português
fig.show()
plotly_plot(fig)

Podemos também fazer gráficos de dispersão (Scatter Plots) para visualizar relações entre duas variáveis. Exemplo: horas trabalhadas por semana vs. capital ganho.

fig = px.scatter(dataset, x="hour-per-week", y="capital-gain", color="income", opacity=0.7, template=custom_template)
fig.update_layout(title="Relação entre Horas Trabalhadas e Capital")
fig.update_layout(xaxis_title="Horas Trabalhadas", yaxis_title="Ganho de Capital")
fig.show()
plotly_plot(fig) 

Para explorar a distribuição de uma variável contínua como idade ou salário por nível educacional, um boxplot é ideal. Iremos discutir mais adiante sobre como o boxplot representa de forma simplicada, as distribuições.

fig = px.box(dataset, x="education", y="age", color="education", template=custom_template)
fig.update_layout(title="Distribuição de Idade por Nível Educacional")
fig.update_layout(xaxis_title="Nível Educacional", yaxis_title="Idade")
fig.show()
plotly_plot(fig)

Para gráficos de linha (Line Plots) um bom exemplo é um dataframe que envolva datas, assim podemos visualizar tendências no tempo. Podemos usar o dataset “Diabetes” do sklearn.datasets, que contém informações sobre pacientes diabéticos, incluindo medições ao longo do tempo.

Segue um exemplo de gráfico de linha usando Plotly:

2.5. Medidas de Tendência Central

As Medidas de Tendência Central são estatísticas que resumem um conjunto de dados indicando um valor central ou típico. Elas são fundamentais para entender a distribuição dos dados e são amplamente utilizadas na Análise Exploratória de Dados (AED).

As principais medidas de tendência central são:

2.5.1. Média

A média aritmética é calculada somando todos os valores e dividindo pelo número total de observações. Ela é sensível a outliers e pode ser influenciada por valores extremos.

A fórmula para a média é $\( \bar{x} = \frac{1}{n} \sum_{i=1}^{n} x_i .\)$ Em Python, podemos calcular a média com o Pandas:

dataset['age'].mean()
38.58164675532078

2.5.2. Mediana

A mediana é o valor central dos dados quando eles estão ordenados. Se houver um número par de elementos, a mediana será a média dos dois valores centrais.

Ela é mais robusta que a média para distribuições assimétricas ou com outliers.

dataset['age'].median()
37.0

2.5.3. Moda

A moda é o valor que mais se repete no conjunto de dados.

Se houver múltiplos valores com a mesma frequência, pode haver mais de uma moda (distribuição multimodal).

Em Python:

dataset['age'].mode()
0    36
Name: age, dtype: int64

2.5.4. Comparação entre as Medidas de Tendência Central

Cada medida de tendência central possui características que a tornam mais apropriada para diferentes situações. A tabela a seguir resume as vantagens e desvantagens de cada uma:

Medida

Vantagem

Desvantagem

Média

Usa todos os valores da amostra, sendo útil para comparações estatísticas.

Sensível a outliers, podendo distorcer a interpretação dos dados.

Mediana

Resistente a outliers e distribuições assimétricas, representando melhor o valor central em dados não normais.

Não utiliza todos os valores na sua determinação.

Moda

Indica o valor mais comum nos dados, sendo útil para variáveis categóricas.

Pode não ser única (distribuição multimodal) ou não existir em conjuntos sem repetições.

A escolha da medida apropriada depende do contexto da análise. Em distribuições simétricas, a média e a mediana costumam ser próximas. Já em distribuições assimétricas ou com outliers, a mediana é uma melhor representação do centro dos dados.

2.5.5. Média Truncada

A média truncada é uma variação da média aritmética em que uma porcentagem dos valores mais altos e mais baixos do conjunto de dados é removida antes do cálculo. Essa abordagem reduz a influência de outliers e valores extremos, tornando-a uma alternativa robusta à média tradicional.

2.5.5.1. Comparação entre Média Truncada e Mediana

Métrica

Média Truncada

Mediana

Definição

Calculada após remover uma fração dos menores e maiores valores do conjunto.

O valor central da distribuição, que divide os dados em duas partes iguais.

Robustez a Outliers

Menos sensível do que a média tradicional, mas ainda pode ser influenciada por valores extremos remanescentes.

Extremamente robusta, pois considera apenas a posição dos dados e não os valores em si.

Uso Recomendado

Quando há outliers moderados, mas a média ainda deve refletir a maioria dos dados.

Quando há outliers extremos ou distribuições altamente assimétricas.

Informação Utilizada

Usa a maioria dos valores, exceto a parte truncada.

Considera apenas a posição relativa dos valores.

2.5.5.2. Exemplo em Python

Podemos calcular a média truncada utilizando a função trim_mean da biblioteca scipy.stats:

from scipy.stats import trim_mean

dados = dataset['age']
media_truncada = trim_mean(dados, proportiontocut=0.1)  # Remove 10% das extremidades
mediana = np.median(dados)

print(f"Média Truncada: {media_truncada}")
print(f"Mediana: {mediana}")
Média Truncada: 37.68981534799801
Mediana: 37.0